package com.qcby.mybatis01.plugin;


import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * @className: SelfPageInterceptor
 * @description: 自定义分页插件
 * @author: lxt
 **/
@Intercepts(
        {
                @Signature(type = Executor.class,method ="query",args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class,method ="query",args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
        }
)
public class SelfPageInterceptor implements Interceptor {

    public Object intercept(Invocation invocation) throws Throwable {
        try {
            // 从 Invocation 中获取参数
            Object[] args = invocation.getArgs();
            MappedStatement ms = (MappedStatement) args[0];
            Object parameter = args[1];
            RowBounds rowBounds = (RowBounds) args[2];
            ResultHandler resultHandler = (ResultHandler) args[3];
            Executor executor = (Executor) invocation.getTarget();
            CacheKey cacheKey;
            BoundSql boundSql;
            //  获取分页参数
            SelfPage page = SelfPageHelper.getPage();
            if (page != null) {
                boundSql = ms.getBoundSql(parameter);
                String pageSql = getPageSql(boundSql,page);
                BoundSql pageBoundSql = new BoundSql(ms.getConfiguration(), pageSql, boundSql.getParameterMappings(), parameter);
                cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
                return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler,cacheKey,pageBoundSql);
            }
            return invocation.proceed();
        }finally {
            SelfPageHelper.removePage();
        }
    }
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    public void setProperties(Properties properties) {

    }

    /**
     * @param boundSql
     * @param page
     * @return
     */
    private String getPageSql(BoundSql boundSql,SelfPage page){
        String sql = boundSql.getSql();
        StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
        sqlBuilder.append(sql);
        if(page.getOffset() > 0){
            sqlBuilder.append("\n LIMIT ")
                    .append(page.getOffset()).append(",").append(page.getPageSize());
        }else{
            sqlBuilder.append("\n LIMIT ").append(page.getPageSize());
        }
        return sqlBuilder.toString();
    }
}
